﻿Imports System.IO
Imports Microsoft.ML
Imports Microsoft.ML.Data

Public Class Tera計算EIQAI
＃Region "AI予測計算予測結果Dgv表示"
    ' ========================================
    ' クラスレベル変数
    ' ========================================
    Private mlContext As MLContext
    Private trainedModels As Dictionary(Of String, ITransformer)
    Private modelFolder As String
    Private 出力フィールド名リスト As List(Of String)
    ' マトリクス表が有効になっているか（EIQマトリクス表実行Bt が押された後に True）
    Private matrixActive As Boolean = False

    ' データ構造定義
    Public Class ModelData
        <LoadColumn(0)> Public モデル連番 As Single
        <LoadColumn(1)> Public 出荷先数 As Single
        <LoadColumn(2)> Public アイテム数 As Single
        <LoadColumn(3)> Public バラ数量 As Single
        <LoadColumn(4)> Public 行数 As Single
        <LoadColumn(5)> Public E1 As Single
        <LoadColumn(6)> Public E2 As Single
        <LoadColumn(7)> Public E3 As Single
        <LoadColumn(8)> Public E4 As Single
        <LoadColumn(9)> Public E5 As Single
        <LoadColumn(10)> Public I1 As Single
        <LoadColumn(11)> Public I2 As Single
        <LoadColumn(12)> Public I3 As Single
        <LoadColumn(13)> Public I4 As Single
        <LoadColumn(14)> Public I5 As Single
        ' 行数01-25, バラ数01-25, ケース01-25, PL01-25, 容積01-25, 重量01-25も同様に定義
        ' (省略：必要に応じて追加)
    End Class

    ' 入力データ構造
    Public Class InputData
        Public 出荷先数 As Single
        Public アイテム数 As Single
    End Class

    ' 単一予測結果クラス
    Public Class SinglePrediction
        <ColumnName("Score")>
        Public Score As Single
    End Class

    ' ========================================
    ' フォームロード
    ' ========================================
    Private Sub Tera計算EIQAI_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ファイル確認()

        Try
            ' MLContextを初期化
            mlContext = New MLContext(seed:=0)
            modelFolder = モデル保存Path
            trainedModels = New Dictionary(Of String, ITransformer)

            ' モデルフォルダの確認
            If Not Directory.Exists(modelFolder) Then
                MsgBox("学習済モデルフォルダが見つかりません。" & vbCrLf &
                      $"フォルダ: {modelFolder}" & vbCrLf & vbCrLf &
                      "モデルファイル(.zip)を上記フォルダに配置してください。",
                      MsgBoxStyle.Exclamation, "フォルダ未検出")
            End If

            ' 出力フィールド名リストを初期化
            出力フィールド名リスト初期化()

            ' 自動的にモデルを読み込む
            学習済モデル読込()

            ' AI予測EIQマトリクス表Dgvのヘッダー初期化
            AI予測EIQマトリクス表Dgv初期化()

        Catch ex As Exception
            MsgBox($"初期化エラー: {ex.Message}", MsgBoxStyle.Critical, "エラー")
        End Try
    End Sub

    ' ========================================
    ' 出力フィールド名リストの初期化
    ' ========================================
    Private Sub 出力フィールド名リスト初期化()
        出力フィールド名リスト = New List(Of String) From {
            "バラ数量", "行数",
            "E1", "E2", "E3", "E4", "E5",
            "I1", "I2", "I3", "I4", "I5"
        }

        ' 行数01-25を追加
        For i As Integer = 1 To 25
            出力フィールド名リスト.Add($"行数{i:D2}")
        Next

        ' バラ数01-25を追加
        For i As Integer = 1 To 25
            出力フィールド名リスト.Add($"バラ数{i:D2}")
        Next

        ' ケース01-25を追加
        For i As Integer = 1 To 25
            出力フィールド名リスト.Add($"ケース{i:D2}")
        Next

        ' PL01-25を追加
        For i As Integer = 1 To 25
            出力フィールド名リスト.Add($"PL{i:D2}")
        Next

        ' 容積01-25を追加
        For i As Integer = 1 To 25
            出力フィールド名リスト.Add($"容積{i:D2}")
        Next

        ' 重量01-25を追加
        For i As Integer = 1 To 25
            出力フィールド名リスト.Add($"重量{i:D2}")
        Next
    End Sub

    ' ========================================
    ' UI初期化 (Designer.vbで管理するためコメントアウト)
    ' ========================================
    'Private Sub InitializeUI()
    '    ' グループボックス1: 入力
    '    Dim gb1 As New GroupBox With {
    '        .Text = "予測条件入力",
    '        .Location = New Point(10, 10),
    '        .Size = New Size(380, 150)
    '    }
    '
    '    Dim lb1 As New Label With {
    '        .Text = "出荷先数:",
    '        .Location = New Point(20, 40),
    '        .Size = New Size(100, 20),
    '        .Font = New Font("MS UI Gothic", 10, FontStyle.Bold)
    '    }
    '    gb1.Controls.Add(lb1)
    '
    '    出荷先数Tb = New TextBox With {
    '        .Location = New Point(130, 37),
    '        .Size = New Size(120, 25),
    '        .Font = New Font("MS UI Gothic", 12)
    '    }
    '    gb1.Controls.Add(出荷先数Tb)
    '
    '    Dim lb2 As New Label With {
    '        .Text = "アイテム数:",
    '        .Location = New Point(20, 80),
    '        .Size = New Size(100, 20),
    '        .Font = New Font("MS UI Gothic", 10, FontStyle.Bold)
    '    }
    '    gb1.Controls.Add(lb2)
    '
    '    アイテム数Tb = New TextBox With {
    '        .Location = New Point(130, 77),
    '        .Size = New Size(120, 25),
    '        .Font = New Font("MS UI Gothic", 12)
    '    }
    '    gb1.Controls.Add(アイテム数Tb)
    '
    '    予測実行Bt = New Button With {
    '        .Text = "予測 実行",
    '        .Location = New Point(20, 110),
    '        .Size = New Size(230, 35),
    '        .Font = New Font("MS UI Gothic", 11, FontStyle.Bold),
    '        .BackColor = Color.LightGreen
    '    }
    '    gb1.Controls.Add(予測実行Bt)
    '
    '    Me.Controls.Add(gb1)
    '
    '    ' グループボックス2: 操作
    '    Dim gb2 As New GroupBox With {
    '        .Text = "操作",
    '        .Location = New Point(400, 10),
    '        .Size = New Size(370, 150)
    '    }
    '
    '    学習済モデル読込Bt = New Button With {
    '        .Text = "学習済モデル 再読込",
    '        .Location = New Point(20, 30),
    '        .Size = New Size(160, 35),
    '        .Font = New Font("MS UI Gothic", 10)
    '    }
    '    gb2.Controls.Add(学習済モデル読込Bt)
    '
    '    結果エクスポートBt = New Button With {
    '        .Text = "結果をCSVに出力",
    '        .Location = New Point(190, 30),
    '        .Size = New Size(160, 35),
    '        .Font = New Font("MS UI Gothic", 10)
    '    }
    '    gb2.Controls.Add(結果エクスポートBt)
    '
    '    モデル状態Lb = New Label With {
    '        .Text = "モデル: 未読込",
    '        .Location = New Point(20, 80),
    '        .Size = New Size(330, 20),
    '        .Font = New Font("MS UI Gothic", 10),
    '        .ForeColor = Color.Blue
    '    }
    '    gb2.Controls.Add(モデル状態Lb)
    '
    '    予測状態Lb = New Label With {
    '        .Text = "予測: 未実行",
    '        .Location = New Point(20, 110),
    '        .Size = New Size(330, 20),
    '        .Font = New Font("MS UI Gothic", 10),
    '        .ForeColor = Color.Gray
    '    }
    '    gb2.Controls.Add(予測状態Lb)
    '
    '    Me.Controls.Add(gb2)
    '
    '    ' DataGridView: 予測結果表示
    '    Dim gb3 As New GroupBox With {
    '        .Text = "予測結果",
    '        .Location = New Point(10, 170),
    '        .Size = New Size(760, 380)
    '    }
    '
    '    予測結果Dgv = New DataGridView With {
    '        .Location = New Point(10, 25),
    '        .Size = New Size(740, 345),
    '        .ReadOnly = True,
    '        .AllowUserToAddRows = False,
    '        .AllowUserToDeleteRows = False,
    '        .SelectionMode = DataGridViewSelectionMode.FullRowSelect,
    '        .Font = New Font("MS UI Gothic", 9)
    '    }
    '    gb3.Controls.Add(予測結果Dgv)
    '
    '    Me.Controls.Add(gb3)
    'End Sub

    ' ========================================
    ' 学習済モデル読込
    ' ========================================
    Private Sub 学習済モデル読込()
        Try
            trainedModels.Clear()

            If Not Directory.Exists(modelFolder) Then
                モデル状態Lb.Text = "モデル: フォルダが見つかりません"
                モデル状態Lb.ForeColor = Color.Red
                Exit Sub
            End If

            ' モデルフォルダ内のすべての.zipファイルを読み込む
            Dim modelFiles = Directory.GetFiles(modelFolder, "*.zip")

            If modelFiles.Length = 0 Then
                モデル状態Lb.Text = "モデル: ファイルが見つかりません"
                モデル状態Lb.ForeColor = Color.Red
                Exit Sub
            End If

            For Each modelPath As String In modelFiles
                Try
                    Dim model = mlContext.Model.Load(modelPath, Nothing)
                    Dim fieldName As String = Path.GetFileNameWithoutExtension(modelPath)
                    trainedModels(fieldName) = model
                Catch ex As Exception
                    ' 読み込めないモデルはスキップ
                    Continue For
                End Try
            Next

            モデル状態Lb.Text = $"モデル: {trainedModels.Count} 個読込済"
            モデル状態Lb.ForeColor = Color.Green

        Catch ex As Exception
            モデル状態Lb.Text = "モデル: 読込エラー"
            モデル状態Lb.ForeColor = Color.Red
            MsgBox($"モデル読込エラー: {ex.Message}", MsgBoxStyle.Critical, "エラー")
        End Try
    End Sub

    ' ========================================
    ' 学習済モデル読込ボタン
    ' ========================================
    Private Sub 学習済モデル読込Bt_Click(sender As Object, e As EventArgs) Handles 学習済モデル読込Bt.Click
        学習済モデル読込()

        If trainedModels.Count > 0 Then
            MsgBox($"{trainedModels.Count} 個のモデルを読み込みました。",
                  MsgBoxStyle.Information, "読込完了")
        End If
    End Sub

    ' ========================================
    ' 予測実行ボタン
    ' ========================================
    Private Sub 予測実行Bt_Click(sender As Object, e As EventArgs) Handles 予測実行Bt.Click
        予測実行()
    End Sub
    Private Sub 予測実行()

        Try
            ' モデルが読み込まれているか確認
            If trainedModels Is Nothing OrElse trainedModels.Count = 0 Then
                MsgBox("モデルが読み込まれていません。" & vbCrLf &
                      "学習済モデルを配置してください。",
                      MsgBoxStyle.Exclamation, "モデル未読込")
                Exit Sub
            End If

            ' 入力値の検証
            Dim 出荷先数値 As Single
            Dim アイテム数値 As Single

            If Not Single.TryParse(出荷先数Tb.Text, 出荷先数値) Then
                MsgBox("出荷先数に有効な数値を入力してください。",
                      MsgBoxStyle.Exclamation, "入力エラー")
                出荷先数Tb.Focus()
                Exit Sub
            End If

            If Not Single.TryParse(アイテム数Tb.Text, アイテム数値) Then
                MsgBox("アイテム数に有効な数値を入力してください。",
                      MsgBoxStyle.Exclamation, "入力エラー")
                アイテム数Tb.Focus()
                Exit Sub
            End If

            ' 入力データを作成
            Dim input As New InputData With {
                .出荷先数 = 出荷先数値,
                .アイテム数 = アイテム数値
            }

            ' 予測状態表示
            予測状態Lb.Text = "予測: 実行中..."
            予測状態Lb.ForeColor = Color.Orange
            Application.DoEvents()

            ' 各モデルで予測を実行
            Dim predictions As New Dictionary(Of String, Single)

            For Each kvp As KeyValuePair(Of String, ITransformer) In trainedModels
                Try
                    Dim fieldName As String = kvp.Key
                    Dim model = kvp.Value

                    ' 予測エンジンを作成（単一出力用）
                    Dim predictionEngine = mlContext.Model.CreatePredictionEngine(Of InputData, SinglePrediction)(model)

                    ' 予測を実行
                    Dim prediction = predictionEngine.Predict(input)

                    ' 結果を保存
                    predictions(fieldName) = prediction.Score

                Catch ex As Exception
                    ' エラーがあればスキップ
                    Continue For
                End Try
            Next

            ' 結果を表示
            予測結果表示(predictions)

            予測状態Lb.Text = $"予測: 完了 ({predictions.Count} 項目)"
            予測状態Lb.ForeColor = Color.Green

            MsgBox($"予測が完了しました。{vbCrLf}{predictions.Count} 項目の予測値を計算しました。",
                  MsgBoxStyle.Information, "予測完了")

        Catch ex As Exception
            予測状態Lb.Text = "予測: エラー"
            予測状態Lb.ForeColor = Color.Red
            MsgBox($"予測エラー: {ex.Message}", MsgBoxStyle.Critical, "エラー")
        End Try
    End Sub

    ' ========================================
    ' 予測結果を表示
    ' ========================================
    Private Sub 予測結果表示(predictions As Dictionary(Of String, Single))
        ' DataGridViewに結果を表示
        Dim dt As New DataTable()
        dt.Columns.Add("項目", GetType(String))
        dt.Columns.Add("予測値", GetType(String))

        ' 出力フィールド名リストの順序に従って予測結果を表示
        For Each fieldName As String In 出力フィールド名リスト
            If predictions.ContainsKey(fieldName) Then
                dt.Rows.Add(fieldName, predictions(fieldName).ToString("F2"))
            End If
        Next

        ' リストにないフィールドも追加（念のため）
        For Each kvp As KeyValuePair(Of String, Single) In predictions
            If Not 出力フィールド名リスト.Contains(kvp.Key) Then
                dt.Rows.Add(kvp.Key, kvp.Value.ToString("F2"))
            End If
        Next

        予測結果Dgv.DataSource = dt
        予測結果Dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    End Sub

    ' ========================================
    ' 結果をCSVにエクスポート
    ' ========================================
    Private Sub 結果エクスポートBt_Click(sender As Object, e As EventArgs) Handles 結果エクスポートBt.Click
        Try
            If 予測結果Dgv.DataSource Is Nothing Then
                MsgBox("エクスポートする予測結果がありません。",
                      MsgBoxStyle.Exclamation, "データなし")
                Exit Sub
            End If

            ' ファイル名を生成（入力条件を含めない簡潔版）
            Dim fileName As String = $"予測結果_{DateTime.Now:yyyyMMdd_HHmmss}.csv"
            Dim exportPath As String = Path.Combine(計算結果Path, fileName)

            ' フォルダが存在しない場合は作成
            Dim exportFolder As String = Path.GetDirectoryName(exportPath)
            If Not Directory.Exists(exportFolder) Then
                Directory.CreateDirectory(exportFolder)
            End If

            ' DataGridViewの内容をCSVに出力（入力条件も含める）
            Dim dt = CType(予測結果Dgv.DataSource, DataTable)

            Using writer As New StreamWriter(exportPath, False, System.Text.Encoding.UTF8)
                ' 入力条件をヘッダーとして出力
                writer.WriteLine($"# 出荷先数,{出荷先数Tb.Text}")
                writer.WriteLine($"# アイテム数,{アイテム数Tb.Text}")
                writer.WriteLine("# ---,")

                ' ヘッダー行（DataGridViewの列名と同じ）
                writer.WriteLine("項目,予測値")

                ' データ行（DataGridViewの内容と同じ）
                For Each row As DataRow In dt.Rows
                    writer.WriteLine($"{row(0)},{row(1)}")
                Next
            End Using

            MsgBox($"予測結果をエクスポートしました。{vbCrLf}保存先: {exportPath}",
                  MsgBoxStyle.Information, "エクスポート完了")

        Catch ex As Exception
            MsgBox($"エクスポートエラー: {ex.Message}", MsgBoxStyle.Critical, "エラー")
        End Try
    End Sub


#End Region
    Private Sub EIQマトリクス表実行Bt_Click(sender As Object, e As EventArgs) Handles EIQマトリクス表実行Bt.Click
        AI予測EIQマトリクス表（)
        matrixActive = True
    End Sub

    ' 表示単位のラジオボタンが変更されたら、マトリクスが有効な場合に再描画する
    Private Sub 抽出_表示単位_CheckedChanged(sender As Object, e As EventArgs) Handles 抽出_出庫回数Rb.CheckedChanged, 抽出_バラRb.CheckedChanged, 抽出_ケースRb.CheckedChanged, 抽出_PLRb.CheckedChanged, 抽出_容積Rb.CheckedChanged, 抽出_重量Rb.CheckedChanged
        If matrixActive Then
            AI予測EIQマトリクス表（)
        End If
    End Sub
＃Region "AI予測EIQマトリクス表作成"
    Private Sub AI予測EIQマトリクス表（)
        Dim nIndex As Integer

        If 抽出_出庫回数Rb.Checked = True Then nIndex = 13
        If 抽出_バラRb.Checked = True Then nIndex = 38
        If 抽出_ケースRb.Checked = True Then nIndex = 63
        If 抽出_PLRb.Checked = True Then nIndex = 88
        If 抽出_容積Rb.Checked = True Then nIndex = 113
        If 抽出_重量Rb.Checked = True Then nIndex = 138

        Try
            ' 予測結果が存在するか確認
            If 予測結果Dgv Is Nothing OrElse 予測結果Dgv.Rows Is Nothing OrElse 予測結果Dgv.Rows.Count = 0 Then
                ' クリア
                抽出I_A1Tb.Text = String.Empty
                抽出I_A2Tb.Text = String.Empty
                抽出I_BTb.Text = String.Empty
                抽出I_CTb.Text = String.Empty
                抽出I_DTb.Text = String.Empty
                抽出I_計Tb.Text = String.Empty
                Return
            End If

            ' ヘルパー: 文字列を四捨五入して整数文字列にする
            Dim Function ToRoundedString(s As String) As String
                If String.IsNullOrWhiteSpace(s) Then Return String.Empty
            Dim d As Double
            If Double.TryParse(s, Globalization.NumberStyles.Any, Globalization.CultureInfo.InvariantCulture, d) Then
                Return CInt(Math.Round(d)).ToString()
            ElseIf Double.TryParse(s, Globalization.NumberStyles.Any, Globalization.CultureInfo.CurrentCulture, d) Then
                Return CInt(Math.Round(d)).ToString()
            Else
                Return String.Empty
            End If
            End Function

            Dim Function ToLongOrZero(s As String) As Long
                Dim v As Long
            If Long.TryParse(s, v) Then Return v
            Return 0
            End Function

            ' 予測結果を辞書にキャッシュ（キー: 項目名, 値: 四捨五入した整数文字列）
            Dim pred As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
            For Each row As DataGridViewRow In 予測結果Dgv.Rows
                If row.IsNewRow Then Continue For
                Dim key = If(row.Cells(0).Value, String.Empty).ToString()
                Dim raw = If(row.Cells(1).Value, String.Empty).ToString()
                If String.IsNullOrEmpty(key) Then Continue For
                pred(key) = ToRoundedString(raw)
            Next

            ' 表示単位プレフィックスを決定
            Dim prefix As String = String.Empty
            If 抽出_出庫回数Rb.Checked = True Then prefix = "行数"
            If 抽出_バラRb.Checked = True Then prefix = "バラ数"
            If 抽出_ケースRb.Checked = True Then prefix = "ケース"
            If 抽出_PLRb.Checked = True Then prefix = "PL"
            If 抽出_容積Rb.Checked = True Then prefix = "容積"
            If 抽出_重量Rb.Checked = True Then prefix = "重量"

            ' アイテム数(I1..I5) と 出荷先数/アイテム数 を抽出して入力欄へ
            抽出I_A1Tb.Text = If(pred.ContainsKey("I1"), pred("I1"), String.Empty)
            抽出I_A2Tb.Text = If(pred.ContainsKey("I2"), pred("I2"), String.Empty)
            抽出I_BTb.Text = If(pred.ContainsKey("I3"), pred("I3"), String.Empty)
            抽出I_CTb.Text = If(pred.ContainsKey("I4"), pred("I4"), String.Empty)
            抽出I_DTb.Text = If(pred.ContainsKey("I5"), pred("I5"), String.Empty)
            出荷先数Tb.Text = If(pred.ContainsKey("出荷先数"), pred("出荷先数"), If(pred.ContainsKey("発送先数"), pred("発送先数"), 出荷先数Tb.Text))
            アイテム数Tb.Text = If(pred.ContainsKey("アイテム数"), pred("アイテム数"), アイテム数Tb.Text)

            ' 抽出I_計Tb に I1〜I5 の合計を設定
            Dim sumI As Long = 0
            sumI += ToLongOrZero(抽出I_A1Tb.Text)
            sumI += ToLongOrZero(抽出I_A2Tb.Text)
            sumI += ToLongOrZero(抽出I_BTb.Text)
            sumI += ToLongOrZero(抽出I_CTb.Text)
            sumI += ToLongOrZero(抽出I_DTb.Text)
            抽出I_計Tb.Text = sumI.ToString()

            ' マトリクス表の埋め込み
            If AI予測EIQマトリクス表Dgv Is Nothing Then Return

            Const dataRows As Integer = 5
            Const dataCols As Integer = 5

            ' 行数を確保（データ行 + 合計行）
            While AI予測EIQマトリクス表Dgv.Rows.Count < dataRows + 1
                AI予測EIQマトリクス表Dgv.Rows.Add()
            End While

            Dim lastColIndex As Integer = AI予測EIQマトリクス表Dgv.Columns.Count - 1
            Dim totalsRowIndex As Integer = dataRows ' 下段

            ' 25セルを一度の辞書参照で埋める
            For r As Integer = 0 To dataRows - 1
                For c As Integer = 1 To dataCols
                    Dim idx As Integer = r * dataCols + (c - 1)
                    Dim k As Integer = idx + 1
                    Dim fieldName As String = prefix & k.ToString("D2")
                    Dim value As String = String.Empty
                    If pred.ContainsKey(fieldName) Then value = pred(fieldName)
                    AI予測EIQマトリクス表Dgv.Rows(r).Cells(c).Value = value
                Next
            Next

            ' 横計（各行）
            For r As Integer = 0 To dataRows - 1
                Dim rowSum As Long = 0
                For c As Integer = 1 To dataCols
                    rowSum += ToLongOrZero(If(AI予測EIQマトリクス表Dgv.Rows(r).Cells(c).Value, String.Empty).ToString())
                Next
                AI予測EIQマトリクス表Dgv.Rows(r).Cells(lastColIndex).Value = rowSum.ToString()
            Next

            ' 縦計（各列）
            For c As Integer = 1 To dataCols
                Dim colSum As Long = 0
                For r As Integer = 0 To dataRows - 1
                    colSum += ToLongOrZero(If(AI予測EIQマトリクス表Dgv.Rows(r).Cells(c).Value, String.Empty).ToString())
                Next
                AI予測EIQマトリクス表Dgv.Rows(totalsRowIndex).Cells(c).Value = colSum.ToString()
            Next

            ' 最下行左のラベルと総合計
            AI予測EIQマトリクス表Dgv.Rows(totalsRowIndex).Cells(0).Value = "横計"
            Dim grandTotal As Long = 0
            For c As Integer = 1 To dataCols
                grandTotal += ToLongOrZero(If(AI予測EIQマトリクス表Dgv.Rows(totalsRowIndex).Cells(c).Value, String.Empty).ToString())
            Next
            AI予測EIQマトリクス表Dgv.Rows(totalsRowIndex).Cells(lastColIndex).Value = grandTotal.ToString()

        Catch ex As Exception
            ' 例外は無視（UIで表示したい場合はここでログ等）
        End Try
    End Sub

    ' ========================================
    ' AI予測EIQマトリクス表Dgvのヘッダー初期化
    ' ========================================
    Private Sub AI予測EIQマトリクス表Dgv初期化()
        ' マトリクス表の列ヘッダーを設定
        AI予測EIQマトリクス表Dgv.Columns.Clear()
        AI予測EIQマトリクス表Dgv.Columns.Add("GPLEランク", "GPLEランク")
        AI予測EIQマトリクス表Dgv.Columns.Add("GPLI_A1", "GPLI_A1")
        AI予測EIQマトリクス表Dgv.Columns.Add("GPLI_A2", "GPLI_A2")
        AI予測EIQマトリクス表Dgv.Columns.Add("GPLI_B", "GPLI_B")
        AI予測EIQマトリクス表Dgv.Columns.Add("GPLI_C", "GPLI_C")
        AI予測EIQマトリクス表Dgv.Columns.Add("GPLI_D", "GPLI_D")
        AI予測EIQマトリクス表Dgv.Columns.Add("横計", "横計")

        ' 列幅を調整
        AI予測EIQマトリクス表Dgv.Columns("GPLEランク").Width = 90
        AI予測EIQマトリクス表Dgv.Columns("GPLI_A1").Width = 80
        AI予測EIQマトリクス表Dgv.Columns("GPLI_A2").Width = 80
        AI予測EIQマトリクス表Dgv.Columns("GPLI_B").Width = 80
        AI予測EIQマトリクス表Dgv.Columns("GPLI_C").Width = 80
        AI予測EIQマトリクス表Dgv.Columns("GPLI_D").Width = 80
        AI予測EIQマトリクス表Dgv.Columns("横計").Width = 90


        ' 0列( GPLEランク ) の0行〜4行にラベルを設定
        Dim labels As String() = {"GPLE_A1", "GPLE_A2", "GPLE_B", "GPLE_C", "GPLE_D"}
        AI予測EIQマトリクス表Dgv.Rows.Clear()
        For Each lbl As String In labels
            AI予測EIQマトリクス表Dgv.Rows.Add(New Object() {lbl, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty})
        Next

        ' すべて右寄せに設定（ヘッダーとセル）
        AI予測EIQマトリクス表Dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        AI予測EIQマトリクス表Dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        For Each col As DataGridViewColumn In AI予測EIQマトリクス表Dgv.Columns
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            col.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight
        Next

        ' 読み取り専用にする
        AI予測EIQマトリクス表Dgv.ReadOnly = True
        ' 行ヘッダーを非表示にする
        AI予測EIQマトリクス表Dgv.RowHeadersVisible = False
    End Sub

    ' ========================================
    ' GPLI_A1..GPLI_D のヘッダーを設定
    ' ========================================
    Private Sub GPLI_A1_D_ヘッダー設定()
        ' GPLI_A1..D列のヘッダーを設定
        予測結果Dgv.Columns("GPLI_A1").HeaderText = "ヘッダーA1"
        予測結果Dgv.Columns("GPLI_A2").HeaderText = "ヘッダーA2"
        予測結果Dgv.Columns("GPLI_A3").HeaderText = "ヘッダーA3"
        予測結果Dgv.Columns("GPLI_A4").HeaderText = "ヘッダーA4"
        予測結果Dgv.Columns("GPLI_A5").HeaderText = "ヘッダーA5"
        予測結果Dgv.Columns("GPLI_B1").HeaderText = "ヘッダーB1"
        予測結果Dgv.Columns("GPLI_B2").HeaderText = "ヘッダーB2"
        予測結果Dgv.Columns("GPLI_B3").HeaderText = "ヘッダーB3"
        予測結果Dgv.Columns("GPLI_B4").HeaderText = "ヘッダーB4"
        予測結果Dgv.Columns("GPLI_B5").HeaderText = "ヘッダーB5"
        予測結果Dgv.Columns("GPLI_C1").HeaderText = "ヘッダーC1"
        予測結果Dgv.Columns("GPLI_C2").HeaderText = "ヘッダーC2"
        予測結果Dgv.Columns("GPLI_C3").HeaderText = "ヘッダーC3"
        予測結果Dgv.Columns("GPLI_C4").HeaderText = "ヘッダーC4"
        予測結果Dgv.Columns("GPLI_C5").HeaderText = "ヘッダーC5"
        予測結果Dgv.Columns("GPLI_D1").HeaderText = "ヘッダーD1"
        予測結果Dgv.Columns("GPLI_D2").HeaderText = "ヘッダーD2"
        予測結果Dgv.Columns("GPLI_D3").HeaderText = "ヘッダーD3"
        予測結果Dgv.Columns("GPLI_D4").HeaderText = "ヘッダーD4"
        予測結果Dgv.Columns("GPLI_D5").HeaderText = "ヘッダーD5"
    End Sub





#End Region

End Class
